#ifndef _NODE_H_
#define _NODE_H_
#include<map>
#include<string>
#include<vector>
#include<fstream>
#include<set>
#include<unistd.h>
#include"SymbolTable.hpp"
#include"ASM.hpp"
using namespace std;


struct TypeNode;
struct FunctionNode;
struct FunctionCallQueue{
    static set<FunctionNode*> flags;
    static vector<FunctionNode*> q;
    static void enQueue(const string& typeName,const string& functionName);
    static void toAsm();
};


enum NodeKind{
    TYPE,
    VARIABLE,
    EXPRESSION,
    PARAMETER,
    FUNCTION,
    PROCESS_STATEMENT
};



struct Node{
    int deep;
    NodeKind nodeKind;
    vector<Node*> child;
    TypeInfo* classScope;
    FunctionMemberInfo* functionScope;

    void setClassScope(TypeInfo* classScope){
        this->classScope = classScope;
    }
    void setFunctionScope(FunctionMemberInfo* functionScope){
        this->functionScope = functionScope;
    }

    TypeInfo* getClassScope(){
        return classScope;
    }
    FunctionMemberInfo* getFunctionScope(){
        return functionScope;
    }

    Node(NodeKind nodeKind):nodeKind(nodeKind),classScope(nullptr),functionScope(nullptr){};
    virtual ~Node(){
    };
    virtual void add_child(Node* node){
        child.push_back(node);
    }
    void setDeep(int deep){
        this->deep = deep;
    }
    int getDeep(){
        return this->deep;
    }
    virtual void toAsm(){}
    virtual string getNodeKind(){
        return "null";
    }
    virtual void show(ofstream& of){
        static char buffer[1024];
        for(int i = 0;i < deep;i++){
            sprintf(buffer,"\t");
            of << (char*)buffer;
        }

        sprintf(buffer,"*结点类型：%s\n",getNodeKind().data());
        of << (char*)buffer;
        for(int i = 0;i < deep;i++){
            sprintf(buffer,"\t");
            of << (char*)buffer;
        }
        sprintf(buffer,"*类作用域：%s\n",getClassScope() == nullptr ? "空" : getClassScope()->typeName.data());
        of << (char*)buffer;
        for(int i = 0;i < deep;i++){
            sprintf(buffer,"\t");
            of << (char*)buffer; 
        }
        sprintf(buffer,"*函数作用域：%s\n\n",getFunctionScope() == nullptr ? "空" : getFunctionScope()->functionMemberName.data());
        of << (char*)buffer;
        for (Node* node : child){
            if (node == nullptr)
                continue;
            node->setDeep(this->getDeep() + 1);
            node->show(of);
        }

    }
    virtual bool check(){
        bool flag = true;
        for (Node* node : child){
            node->setClassScope(getClassScope());
            node->setFunctionScope(getFunctionScope());
            if (node->check() == false)
                flag = false;
        }
        
        return flag;
    }
};

struct Offset
{
    virtual string getOffset(){return "null offset";}
    // 感觉没什么用
};





struct ExpressionNode : public Node{
    Register reg;
    TypeInfo* resultTypeInfo;
    Location location;

    int offset;
    void setOffset(int offset){
        this->offset = offset;
    }
    int getOffset(){
        return this->offset;
    }
    ExpressionNode(Location location):Node(NodeKind::EXPRESSION),location(location),offset(0){}
    ~ExpressionNode(){
        reg.freeRegister();
    }
    virtual vector<string> getValue() = 0;

    void setResultTypeInfo(TypeInfo* resultTypeInfo){
        this->resultTypeInfo = resultTypeInfo;
    }
    virtual string getNodeKind(){
        return "表达式";
    }
    TypeInfo* getResultTypeInfo(){
        return this->resultTypeInfo;
    }

    void allocateRegister(){
        reg.allocateRegister();
    }
    void moveRegister(ExpressionNode* expressionNode){
        this->reg.moveRegister(expressionNode->reg);
    }
    void freeRegister(){
        reg.freeRegister();
    }
    Register* getRegister(){
        return &reg;
    }


};

enum VariableKind{
    UNKNOWN,
    DATA_MEMBER,            // 数据成员
    RETURN_TEMP,                 // 返回值
    FORMAL_PARAMETER,       // 形参
    LOCAL                   // 局部变量
};

// 形参 及 局部变量
struct VariableNode : public ExpressionNode{
    string variableName;
    Entity* var;
    VariableKind variableKind;

    VariableNode(const string& variableName):
        ExpressionNode(Location::MEMORY),
        variableName(variableName),
        variableKind(VariableKind::UNKNOWN)
        {}

    VariableNode(TypeInfo* typeInfo,VariableKind variableKind):ExpressionNode(Location::MEMORY){
        setResultTypeInfo(typeInfo);
        setVariableKind(variableKind);
    }

    void setVariableKind(VariableKind variableKind){
        this->variableKind = variableKind;
    }
    virtual string getNodeKind(){
        if (variableKind == VariableKind::RETURN_TEMP)
            return "返回值(" + getResultTypeInfo()->typeName + ")";
        return "变量(" + var->typeInfo->typeName + " " + variableName + ")";
    }

    bool check(){
        if (variableKind == VariableKind::RETURN_TEMP)
            return true;

        bool flag = true;
        if (functionScope != nullptr){
            var = symbolTable.getParameter(functionScope,variableName);

            if (var != nullptr){
                this->setVariableKind(VariableKind::FORMAL_PARAMETER);
                goto RETURN_FLAG;
            }

            var = symbolTable.getLocalVariable(functionScope,variableName);
            if (var != nullptr){
                this->setVariableKind(VariableKind::LOCAL);
                goto RETURN_FLAG;
            }
        }
        /*else{
            printf("错误：成员%s的函数作用域未知\n",variableName.data());
            goto RETURN_FLAG;
            当时给它加上，好像是因为this指针
        }*/

        if (getClassScope() != nullptr){
            var = symbolTable.getDataMember(getClassScope(),variableName);
            if (var != nullptr){
                this->setVariableKind(VariableKind::DATA_MEMBER);
                goto RETURN_FLAG;
            }
        }

        RETURN_FLAG:
        if (var == nullptr){
            printf("错误：无法获得实体%s的相关信息\n",variableName.data());
            flag = false;
        }
        else if (var->accessModifier == AccessModifier::PRIVATE && getFunctionScope()->classScope != getClassScope()){
            printf("错误：成员%s::%s不可访问\n",getClassScope()->typeName.data(),variableName.data());
            flag = false;
        }
        else{
            setResultTypeInfo(var->typeInfo);
            setOffset(var->offset);
        }
        return flag;
    }
    vector<string> value;



    void _getValue(TypeInfo* typeInfo,int offset){
        char variableOffset[64];

        switch (variableKind)
        {
        case VariableKind::DATA_MEMBER:
            if (typeInfo->typeKind == TypeKind::CLASS_TYPE){
                for (auto& member : typeInfo->dataMember){
                    _getValue(member.typeInfo,offset);
                    offset += member.typeInfo->size;
                }
            }
            else{
                sprintf(variableOffset,"[esi%+d]", offset);
                value.push_back(variableOffset);
            }
            break;

        case VariableKind::FORMAL_PARAMETER:
            if (typeInfo->typeKind == TypeKind::CLASS_TYPE){
                for (auto& member : typeInfo->dataMember){
                    _getValue(member.typeInfo,offset);
                    offset += member.typeInfo->size;
                }
            }
            else{
                sprintf(variableOffset,"[ebp%+d]",offset);
                value.push_back(variableOffset);
            }
            break;
            
        case VariableKind::LOCAL:
            if (typeInfo->typeKind == TypeKind::CLASS_TYPE){
                for (auto& member : typeInfo->dataMember){
                    _getValue(member.typeInfo,offset);
                    offset += member.typeInfo->size;
                }
            }
            else{
                sprintf(variableOffset,"[ebp%+d]",offset);
                value.push_back(variableOffset);
            }
            break;
        case VariableKind::RETURN_TEMP:
            if (typeInfo->typeKind == TypeKind::CLASS_TYPE){
                for (auto& member : typeInfo->dataMember){
                    _getValue(member.typeInfo,offset);
                    offset += member.typeInfo->size;
                }
            }
            else{
                sprintf(variableOffset,"[ebp%+d]",offset);
                value.push_back(variableOffset);
            }
            break;
        default:
            break;
        }
    }


    vector<string> getValue(){
        value.clear();
        if (variableKind == VariableKind::RETURN_TEMP){
            int offset = getFunctionScope()->parameter_block_size + PARAMETER_INIT_OFFSET + 4 ;
            _getValue(getResultTypeInfo(),offset);
        }
        else if (variableKind == VariableKind::DATA_MEMBER){

            string this_mem = "[ebp+8]";
            ASM::move_this_to_esi(this_mem);
            _getValue(var->typeInfo,var->offset);

                    //ASM::add_esp(functionInfo->parameter_block_size + 4);     // 调用者清栈
        }
        else
            _getValue(var->typeInfo,var->offset);
        return value;
    }

};


enum ConstantType{
    BOOL,
    INT
};

struct ConstantNode : public ExpressionNode{
    bool isSigned;

    long long value;

    ConstantType constantType;
    ConstantNode(const string& num,ConstantType constantType):
        ExpressionNode(Location::CONSTANT),
        constantType(constantType){
        value = atoll(num.data());
    }

    void resetConstantType(ConstantType constantType){
        this->constantType = constantType;
    }

    vector<string> getValue(){
        vector<string> temp;
        
        temp.push_back(to_string(value));
        return temp;
    }
    bool check(){
        bool flag = true;
        switch (constantType)
        {
        case ConstantType::BOOL:
            setResultTypeInfo(symbolTable.getTypeInfo("bool"));
        case ConstantType::INT:
            setResultTypeInfo(symbolTable.getTypeInfo("int32"));
        default:
            break;
        }
        /*unsigned long long result = 0;
        for(char ch : num){
            unsigned long long temp = result;
            result = result * 10 + ch - '0';

            if (result < temp){
                flag = false;
                break;
            }
        }
        if (flag == false)
            printf("%s无法准确表示，超出了uint64的表示范围\n",num.data());*/
        return flag;
    }
    virtual string getNodeKind(){
        switch (constantType)
        {
        case ConstantType::BOOL:
            if (value == 0)
                return "常量(bool false)";
            else
                return "常量(bool true)";              
        case ConstantType::INT:
            return "常量(int32 " + to_string(value) + ")";
        }
        return "常量(unknown)";
    }
    void toAsm(){
        this->allocateRegister();
        ASM::move_temp_to_reg(to_string(value),*(this->getRegister()),symbolTable.getTypeInfo("int32"));
    }
};

struct StringNode : public ExpressionNode{
    static vector<pair<string,string>> stringTable;
    string value;
    string label;
    StringNode(const string& str):ExpressionNode(Location::REGISTER),value(str){
        value.front() = value.back() = '\'';
    }
    bool check(){
        return true;
    }
    virtual string getNodeKind(){
        return "字符串(" + value + ")";
    }
    void toAsm(){
        usleep(100000);
        printf("正在编译字符串结点...\n");
        this->allocateRegister();
        label = ASM::getStringLabel();
        stringTable.push_back({label,value});
    }

    vector<string> getValue(){
        vector<string> temp;
        temp.push_back(label);
        return temp;
    }
};
inline vector<pair<string,string>> StringNode::stringTable;


enum OP{
    ADD,
    SUB,
    MUL,
    DIV,
    MOD,
    EQUAL,
    DOT,
    AND,OR,NOT,XOR,                           // 与 或 非 异或
    LAND,LOR,LNOT,                         // 逻辑与或非
    LT,LE,EQ,NE,GE,GT                        // < <= == != >= >
};
inline array<string,20> OP_STR = {
    "+",    "-",    "*",    "/",    "=",
    ".",
    "&",    "|",    "~",    "^",
    "&&",   "||",   "!",
    "<",    "<=",   "==",   "!=",   ">=",   ">"
};


struct ParametersNode : public Node{
    vector<ExpressionNode*> parameters;
    // 返回值（栈里）变量 常量--内存 表达式--寄存器
    ParametersNode():Node(NodeKind::PARAMETER){}
    void addParameter(ExpressionNode* expressionNode){
        parameters.push_back(expressionNode);
    }

}; 


struct FunctionCallNode : public ExpressionNode{
    vector<ExpressionNode*> parameters;
    string functionName;
    TypeInfo* accessClassScope;
    FunctionMemberInfo* functionInfo;
    bool freeReturnMemory;
    string variableAddress;



    FunctionCallNode(const string& functionName,vector<ExpressionNode*> parameters):
        ExpressionNode(Location::RETURN),
        accessClassScope(nullptr),
        functionInfo(nullptr),
        functionName(functionName),
        parameters(parameters),
        freeReturnMemory(true){}
    ~FunctionCallNode(){
        for (auto& param : parameters)
            delete param;
        if (freeReturnMemory == true)
            ASM::add_esp(getResultTypeInfo()->size);
            //ASM::add_esp(functionInfo->returnType->size);
    }
    void setAccessClassScope(TypeInfo* accessClassScope){
        this->accessClassScope = accessClassScope;
    }
    void setVariableAddress(const string& variableAddress){
        this->variableAddress = variableAddress;
    }

    virtual string getNodeKind(){
        return "函数调用(" + functionName + ")";
    }
    TypeInfo* getAccessClassScope(){
        return this->accessClassScope;
    }
    void toAsm(){
        string str = getAccessClassScope()->typeName + "::" + functionName;

        FunctionCallQueue::enQueue(getAccessClassScope()->typeName,functionName);
        usleep(100000);
        printf("正在编译函数调用结点（调用%s::%s）...\n",getAccessClassScope()->typeName.data(),functionName.data());
        ASM::sub_esp(functionInfo->returnType->size);
        for (auto& param : parameters){
            usleep(100000);
            printf("正在处理函数传参（%s::%s）...\n",getAccessClassScope()->typeName.data(),functionName.data());
            if (param->location == Location::CONSTANT)
                ASM::push_constant(param->getValue().front());
            else{
                param->toAsm();
                param->allocateRegister();
                //ASM::push_register(*(param->getRegister()));
                // 下面这个不能去,它是要根据参数的类型(返回值 局部变量等)来进行传餐操作的
                ASM::push(param->getValue(),*(param->getRegister()),param->getResultTypeInfo(),param->location);
                param->freeRegister();
            }
            if (param->location == Location::RETURN)
                static_cast<FunctionCallNode*>(param)->freeReturnMemory = false;
            param->freeRegister();
        }
        this->allocateRegister();
        if (variableAddress.empty() == false){
            ASM::lea(*(this->getRegister()),variableAddress);
            ASM::push(this->getRegister()->getRegister32());
        }
        else 
            ASM::push("DWORD [ebp+8]");
        

        this->freeRegister();

        ASM::callFunction(accessClassScope->typeName,functionName);
        ASM::add_esp(functionInfo->parameter_block_size + 4);     // 调用者清栈
        //ASM::add_esp(functionInfo->local_variable_block_size);

    }

    vector<string> getValue(){
        vector<string> temp;
        char variableOffset[32];
        int offset = functionInfo->parameter_block_size + PARAMETER_INIT_OFFSET + 4 ;
        sprintf(variableOffset,"[esp]",offset);
        temp.push_back(variableOffset);
        return temp;
    }

    bool check(){

        if (getAccessClassScope() == nullptr){
            if (getFunctionScope()->functionMemberName != "main")
                setAccessClassScope(getClassScope());
            else{
                printf("错误：成员函数%s所属类未知\n",functionName.data());
                return false;
            }
        }


        functionInfo = symbolTable.getFunctionMemberInfo(getAccessClassScope(),functionName);
        if (functionInfo == nullptr){
            printf("错误：获取%s::%s()的信息失败\n",getAccessClassScope()->typeName.data(),functionName.data());
            return false;
        }

        if (functionInfo->accessModifier == AccessModifier::PRIVATE){
            printf("错误：成员%s::%s()不可访问\n",getAccessClassScope()->typeName.data(),functionName.data());
            return false;
        }
        
        if (this->parameters.size() != this->functionInfo->parameters.size()){
            printf("错误：类%s的成员函数%s接收%d个参数，而调用时传入%d个参数\n",functionInfo->classScope->typeName.data(),functionInfo->functionMemberName.data(),functionInfo->parameters.size(),parameters.size());
            return false;
        }

        bool flag = true;
        for (auto& param : parameters){
            param->setClassScope(getClassScope());
            param->setFunctionScope(getFunctionScope());
            if (param->check() == false)
                flag = false;
        }

        bool isConsistent = true;
        for (int i = 0;i < parameters.size();i++){
            if (parameters[i]->getResultTypeInfo()->typeName != this->functionInfo->parameters[i].typeInfo->typeName){
                isConsistent = false;
                break;
            }
        }
        if (isConsistent == false){
            printf("错误：传入参数列表与%s::%s(",functionInfo->classScope->typeName.data(),functionInfo->functionMemberName.data());
            for (int i = 0;i < this->functionInfo->parameters.size();i++){
                if (i == 0)
                    printf("%s",this->functionInfo->parameters[i].dataMemberName.data());
                else
                    printf(",%s",this->functionInfo->parameters[i].dataMemberName.data());
            }
            printf(")不符\n");
        }
        setResultTypeInfo(functionInfo->returnType);
        setOffset(0);
        return flag && isConsistent;
    }
    
};



struct UnaryOperatorNode : public ExpressionNode
{
    OP op;
    ExpressionNode* var;
    UnaryOperatorNode(ExpressionNode* var,OP op):
        ExpressionNode(Location::REGISTER),
        var(var),
        op(op)
        {}
    virtual string getNodeKind(){
        switch (op)
        {
        case OP::NOT:
            return "一元运算符(位运算非)";
        case OP::LNOT :         
            return "一元运算符(逻辑运算非)";
        default:
            break;
        }
        return "一元运算符(unknown)";
    }
    vector<string> getValue(){
        vector<string> temp;
        temp.push_back(getRegister()->getRegister32());
        return temp;
    }
    bool check(){

        bool flag = true;

        var->setClassScope(getClassScope());
        var->setFunctionScope(getFunctionScope());
        if (var->check() == false)  
            flag = false;
        if (var->getResultTypeInfo()->typeKind == TypeKind::CLASS_TYPE){
            printf("错误：类型%s没有对应的运算符%s\n",var->getResultTypeInfo()->typeName.data(),OP_STR[op].data());
            flag = false;
        }



        switch (op)
        {
        case OP::NOT:
            setResultTypeInfo(symbolTable.getTypeInfo("int32"));
            break;
        case OP::LNOT :         
            setResultTypeInfo(symbolTable.getTypeInfo("bool"));
            break;
        default:
            break;
        }
        return flag;
    }

    void toAsm(){
        usleep(100000);
        printf("正在编译一元运算[%s]...\n",OP_STR[op].data());

        var->toAsm();
        var->allocateRegister();
        vector<string> var_value = var->getValue();
        Register* var_reg = var->getRegister();

        switch (op)
        {
        case OP::NOT:
            ASM::bit_not(*var_reg);
            break;
        case OP::LNOT :         
            ASM::cmp(*var_reg,0);
            ASM::sete(*var_reg);

            break;
        default:
            break;
        }
        this->moveRegister(var); 
    }
};





struct BinaryOperatorNode : public ExpressionNode{
    OP op;
    
    ExpressionNode* var1;
    ExpressionNode* var2;

    

    BinaryOperatorNode(ExpressionNode* var1_node,ExpressionNode* var2_node,OP op):
        ExpressionNode(Location::REGISTER),op(op),var1(var1_node),var2(var2_node){
            child.push_back(var1_node);
            child.push_back(var2_node);
        }
    void toAsm(){
        usleep(100000);
        printf("正在编译二元运算[%s]...\n",OP_STR[op].data());
        if (op == OP::DOT){
            var1->toAsm();
            var1->freeRegister();
            if (var2->location == Location::RETURN){
                static_cast<FunctionCallNode*>(var2)->setClassScope(var1->getResultTypeInfo());
            }
            else if (var2->location == Location::MEMORY){
                static_cast<VariableNode*>(var2)->setClassScope(var1->getResultTypeInfo());
            }
            var2->toAsm();
            var2->freeRegister();
            return;
        }

        var1->toAsm();
        var2->toAsm();


        var1->allocateRegister();
        var2->allocateRegister();

        vector<string> var1_value = var1->getValue();
        vector<string> var2_value = var2->getValue();

        Register* var1_reg = var1->getRegister();
        Register* var2_reg = var2->getRegister();



        if (op == OP::EQUAL){
            for (int i = 0;i < var1_value.size();i++){
                if (var2->location != Location::MEMORY)
                    ASM::move_temp_to_reg(var2_value[i],*var2_reg,var2->getResultTypeInfo());
                else
                    ASM::move_mem_to_reg(var2_value[i],*var2_reg,var2->getResultTypeInfo());
                
                ASM::move_reg_to_mem(var1_value[i],*var2_reg,var1->getResultTypeInfo());
            }
            this->moveRegister(var1); 
            var2->freeRegister();
            return;
        }

        // 常数的运算会在编译时算出，所以不可能两个操作数都是常数
        // 变量  返回值  都在内存 
        // 寄存器 常量
        if (var1->location == Location::CONSTANT)   ASM::move_temp_to_reg(var1_value.front(),*var1_reg,var1->getResultTypeInfo());
        else if (var1->location != Location::REGISTER)  ASM::move_mem_to_reg(var1_value.front(),*var1_reg,var1->getResultTypeInfo());
        
        if (var2->location == Location::CONSTANT)   ASM::move_temp_to_reg(var2_value.front(),*var2_reg,var2->getResultTypeInfo());
        else if (var2->location != Location::REGISTER)  ASM::move_mem_to_reg(var2_value.front(),*var2_reg,var2->getResultTypeInfo());
        
        /*if (var1->location != Location::MEMORY){
            if (var1->location == Location::CONSTANT)
                ASM::move_temp_to_reg(var1_value.front(),*var1_reg,var1->getResultTypeInfo());
            ASM::move_mem_to_reg(var2_value.front(),*var2_reg,var2->getResultTypeInfo());
        }
        else if (var2->location != Location::MEMORY){
            ASM::move_mem_to_reg(var1_value.front(),*var1_reg,var1->getResultTypeInfo());
            ASM::move_temp_to_reg(var2_value.front(),*var2_reg,var2->getResultTypeInfo());
        }else{  // 两个操作数都不是常数——都在内存中
            ASM::move_mem_to_reg(var1_value.front(),*var1_reg,var1->getResultTypeInfo());
            ASM::move_mem_to_reg(var2_value.front(),*var2_reg,var2->getResultTypeInfo());
        }*/


        switch (op)
        {
        case OP::ADD:{
            ASM::add(*var1_reg,*var2_reg);
            break;
        }
        case OP::SUB:{
            ASM::sub(*var1_reg,*var2_reg);
            break;
        }
        case OP::MUL:{
            ASM::imul(*var1_reg,*var2_reg);
            break;
        }
        case OP::DIV:{
            ASM::div(*var1_reg,*var2_reg);
            break;
        }
        case OP::EQUAL:{
            ASM::move_reg_to_mem(var1_value.front(),*var2_reg,var1->getResultTypeInfo());
            break;
        }



        case OP::AND:
            ASM::bit_and(*var1_reg,*var2_reg);
            break;
        case OP::OR:
            ASM::bit_or(*var1_reg,*var2_reg);
            break;
/*        case OP::NOT:                            // 一元运算符
            printf("位取反运算\n");
            ASM::bit_or(*var1_reg,*var2_reg);
            break;*/



        case OP::LT:{
            ASM::cmp(*var1_reg,*var2_reg);
            ASM::setl(*var1_reg);
            break;
        }
        case OP::LE:{
            ASM::cmp(*var1_reg,*var2_reg);
            ASM::setle(*var1_reg);
            break;
        }
        case OP::EQ:
            ASM::cmp(*var1_reg,*var2_reg);
            ASM::sete(*var1_reg);
            break;
        case OP::NE:
            ASM::cmp(*var1_reg,*var2_reg);
            ASM::setne(*var1_reg);
            break;
        case OP::GE:
            ASM::cmp(*var1_reg,*var2_reg);
            ASM::setge(*var1_reg);
            break;
        case OP::GT:
            ASM::cmp(*var1_reg,*var2_reg);
            ASM::setg(*var1_reg);
            break;



        case OP::LAND:{
            string label_1 = ASM::getRandomLabel();
            string label_2 = ASM::getRandomLabel();
            ASM::cmp(*var1_reg,0);
            ASM::je(*var1_reg,label_1);
            ASM::cmp(*var2_reg,0);
            ASM::je(*var2_reg,label_1);
            
            ASM::move_temp_to_reg("1",*var1_reg,symbolTable.getTypeInfo("int32"));
            ASM::jmp(label_2);
            
            ASM::setLabel(label_1);
            ASM::move_temp_to_reg("0",*var1_reg,symbolTable.getTypeInfo("int32"));
            
            ASM::setLabel(label_2);
            break;
        }
        case OP::LOR:{
            string label_1 = ASM::getRandomLabel();
            string label_2 = ASM::getRandomLabel();
            string label_3 = ASM::getRandomLabel();

            ASM::cmp(*var1_reg,0);
            ASM::jne(*var1_reg,label_1);
            ASM::cmp(*var2_reg,0);
            ASM::je(*var2_reg,label_2);

            ASM::setLabel(label_1);
            ASM::move_temp_to_reg("1",*(this->getRegister()),symbolTable.getTypeInfo("int32"));
            ASM::jmp(label_3);

            ASM::setLabel(label_2);
            ASM::move_temp_to_reg("0",*(this->getRegister()),symbolTable.getTypeInfo("int32"));
            
            ASM::setLabel(label_3);
            break;
        }
        default:
            break;
        }
        this->moveRegister(var1); 
        var2->freeRegister();
        // 如果是临时变量，那只有放在寄存器中了
        // 如果是局部变量，

    }
    virtual string getNodeKind(){
        switch (op)
        {
        case OP::ADD:
            return "二元运算符(加法)";
        case OP::SUB:
            return "二元运算符(减法)";
        case OP::MUL:
            return "二元运算符(乘法)";
        case OP::DIV:
            return "二元运算符(除法)";
        case OP::EQUAL:
            return "二元运算符(赋值)";
        case OP::AND:
            return "二元运算符(bit与运算)";
        case OP::OR:
            return "二元运算符(bit或运算)";


        case OP::LT:
            return "二元运算符(小于)";
        case OP::LE:
            return "二元运算符(小于等于)";
        case OP::EQ:
            return "二元运算符(相等)";
        case OP::NE:
            return "二元运算符(不等)";
        case OP::GE:
            return "二元运算符(大于等于)";
        case OP::GT:
            return "二元运算符(大于)";



        case OP::LAND:
            return "二元运算符(bool与运算)";
        case OP::LOR:
            return "二元运算符(bool或运算)";
        default:
            break;
        }
        return "二元运算符(unknown)";
    }
    bool check(){
        bool flag = true;

        if (op == OP::DOT){
            var1->setClassScope(getClassScope());
            var1->setFunctionScope(getFunctionScope());
            if (var1->check() == false)
                flag = false;



            if (var2->location == Location::CONSTANT){
                printf("错误：常量不存在\“.\”运算\n");
                return false;
            }

            // 就是如果访问的是成员函数
            if (var2->location == Location::RETURN){
                var2->setClassScope(getClassScope());
                var2->setFunctionScope(getFunctionScope());
                static_cast<FunctionCallNode*>(var2)->setAccessClassScope(var1->getResultTypeInfo());
                static_cast<FunctionCallNode*>(var2)->setVariableAddress(var1->getValue().front());
                this->location = Location::RETURN;
            }
            else{   // 否则的话访问的就是成员变量了
                var2->setClassScope(var1->getResultTypeInfo());
                var2->setFunctionScope(getFunctionScope());
                this->location = Location::MEMORY;
            }
            if (var2->check() == false)
                flag = false;

            setOffset(var2->getOffset());
            setResultTypeInfo(var2->getResultTypeInfo());
            return flag;
        }


        var1->setClassScope(getClassScope());
        var1->setFunctionScope(getFunctionScope());

        var2->setClassScope(getClassScope());
        var2->setFunctionScope(getFunctionScope());

        var1->check();
        var2->check();

        TypeInfo* typeInfo1 = var1->getResultTypeInfo();
        TypeInfo* typeInfo2 = var2->getResultTypeInfo();
        if (typeInfo1 == nullptr || typeInfo2 == nullptr){
            printf("错误：表达式中存在未知的类型信息\n");
            flag = false;
        }

        switch (op)
        {
        case OP::ADD:
        case OP::SUB:
        case OP::MUL:
        case OP::DIV:
            if (typeInfo1->typeKind == TypeKind::CLASS_TYPE){
                printf("错误：%s类型不存在运算符\"%s\"\n",typeInfo1->typeName.data(),OP_STR[op].data());
                flag = false;
            }
            else if (typeInfo2->typeKind == TypeKind::CLASS_TYPE){
                printf("错误：%s类型不存在运算符\"%s\"\n",typeInfo2->typeName.data(),OP_STR[op].data());
                flag = false;
            }
            else
                setResultTypeInfo(typeInfo1->typeKind >= typeInfo2->typeKind ? typeInfo1 : typeInfo2);

            break;
        
        case OP::EQUAL:
            if (var1->location != Location::MEMORY){
                printf("错误：运算符\"=\"左边必须为左值\n");
                return false;
            }
            else if (var1->getResultTypeInfo()->typeKind == TypeKind::CLASS_TYPE && var2->getResultTypeInfo()->typeKind != TypeKind::CLASS_TYPE){
                printf("错误：%s类型的数据无法被%s类型的数据赋值\n",var1->getResultTypeInfo()->typeName.data(),var2->getResultTypeInfo()->typeName.data());
                return false;
            }
            else if (var1->getResultTypeInfo()->typeKind != TypeKind::CLASS_TYPE && var2->getResultTypeInfo()->typeKind == TypeKind::CLASS_TYPE){
                printf("错误：%s类型的数据无法被%s类型的数据赋值\n",var1->getResultTypeInfo()->typeName.data(),var2->getResultTypeInfo()->typeName.data());
                return false;
            }
            else
                setResultTypeInfo(typeInfo1);
            
            break;

        case OP::AND:
        case OP::OR:
            if (typeInfo1->typeKind == TypeKind::CLASS_TYPE){
                printf("%s类型不存在运算符\"%s\"\n",typeInfo1->typeName.data(),OP_STR[op].data());
                flag = false;
            }
            else if (typeInfo2->typeKind == TypeKind::CLASS_TYPE){
                printf("%s类型不存在运算符\"%s\"\n",typeInfo2->typeName.data(),OP_STR[op].data());
                flag = false;
            }
            else
                setResultTypeInfo(typeInfo1->typeKind >= typeInfo2->typeKind ? typeInfo1 : typeInfo2);
            break;
        case OP::LT:
        case OP::LE:
        case OP::EQ:
        case OP::NE:
        case OP::GE:
        case OP::GT:
            if (typeInfo1->typeKind == TypeKind::CLASS_TYPE){
                printf("%s类型不存在运算符\"%s\"\n",typeInfo1->typeName.data(),OP_STR[op].data());
                flag = false;
            }
            else if (typeInfo2->typeKind == TypeKind::CLASS_TYPE){
                printf("%s类型不存在运算符\"%s\"\n",typeInfo2->typeName.data(),OP_STR[op].data());
                flag = false;
            }
            else
                setResultTypeInfo(symbolTable.getTypeInfo("bool"));
            break;
        default:
            break;
        }

        return flag;
    }
    ~BinaryOperatorNode(){
        delete var1;
        delete var2;
    }
    vector<string> getValue(){
        if (op == OP::DOT){
            if (var2->location == Location::RETURN)
                return var2->getValue();
            else{
                vector<string> temp;
                if (var1->location == Location::MEMORY){
                    int offset = var1->getOffset();
                    char buffer[64];
                    sprintf(buffer,"[ebp%+d]",offset);
                    temp.push_back(buffer);
                    return temp;
                }
                else if (var1->location == Location::RETURN){
                    int offset = var1->getOffset();
                    char buffer[64];
                    sprintf(buffer,"[esp%+d]",offset);
                    temp.push_back(buffer);
                    return temp;
                }
                else{
                    printf("错误：未知的错误\n");
                    return temp;
                }
            }
        }
        

        vector<string> temp;
        temp.push_back(getRegister()->getRegister32());
        return temp;
    }
};




struct FunctionNode : public Node{
    string functionName;
    FunctionNode(const string& functionName):
        Node(NodeKind::FUNCTION),
        functionName(functionName)
        {}
    virtual string getNodeKind(){
        string staticStr, accessStr, returnStr, funStr;
        staticStr = getFunctionScope()->isStatic ? "static" : "non-static";
        if (getFunctionScope()->accessModifier == AccessModifier::PUBLIC)   accessStr = "public";
        else if (getFunctionScope()->accessModifier == AccessModifier::PRIVATE) accessStr = "private";
        returnStr = getFunctionScope()->returnType->typeName;
        funStr = getFunctionScope()->functionMemberName;
        return "函数定义(" + staticStr + " " + accessStr + " " + returnStr + " " + funStr + ")";
    }
    bool check(){
        bool flag = true;

        if (classScope == nullptr){
            printf("函数%s所属类未知\n",functionName.data());
            flag = false;
        }
        else{
            FunctionMemberInfo* temp = symbolTable.getFunctionMemberInfo(getClassScope(),functionName);
            this->setFunctionScope(temp);

            symbolTable.set_current_function_scope(functionName);
            for (Node* node : child){
                node->setClassScope(getClassScope());
                node->setFunctionScope(getFunctionScope());
                if (node->check() == false)
                    flag = false;
            }
        }
        return flag;
    }
    void toAsm(){
        //symbol_table.set_current_function_scope(*(string*)content);
        //printf(".%s:\n",((string*)content)->data());
        ASM::setFunctionLabel(getClassScope()->typeName,getFunctionScope()->functionMemberName);

        ASM::function_entry(getFunctionScope()->local_variable_block_size);

        for (Node* node : child)
            node->toAsm();
        
        ASM::function_return();

    }
};
struct EntryNode : public FunctionNode{
    EntryNode():FunctionNode("main"){}

    bool check(){
        bool flag = true;

        symbolTable.set_current_function_scope(functionName);
        this->setFunctionScope(symbolTable.getEntryInfo());
        this->setClassScope(nullptr);

        for (Node* node : child){
            node->setClassScope(getClassScope());
            node->setFunctionScope(symbolTable.getEntryInfo());
            if (node->check() == false)
                flag = false;
        }
        
        return flag;
    }
        virtual string getNodeKind(){
            return "程序入口(public int32 main)";
    }
    void toAsm(){

        //symbol_table.set_current_function_scope(*(string*)content);
        //printf(".%s:\n",((string*)content)->data());
        usleep(100000);
        printf("正在编译入口函数main...\n");
        symbolTable.set_current_function_scope("main");
        ASM::extern_label("printf");
        ASM::global("main");
        ASM::setLabel("main");

        ASM::function_entry(getFunctionScope()->local_variable_block_size);
        
        for (Node* node : child){
            node->toAsm();
            delete node;
        }
        
        ASM::function_return();


        FunctionCallQueue::toAsm();

        for (auto& str : StringNode::stringTable){
            ASM::setLabel(str.first);
            ASM::setString(str.second);
        }
    }
};



struct TypeNode : public Node
{
    string typeName;
    TypeInfo* typeInfo;
    map<string,FunctionNode*> functionMemberNode;
    EntryNode* entryNode;
public:
    TypeNode():Node(NodeKind::TYPE),typeInfo(nullptr),entryNode(nullptr),typeName(){}
    TypeInfo* getTypeInfo(){
        if (typeInfo == nullptr)
            typeInfo = symbolTable.getTypeInfo(typeName);
        return typeInfo;
    }
    virtual string getNodeKind(){
        return "类(" + typeName + ")";
    }
    void setTypeName(const string& typeName){

        this->typeName = typeName;
    }
    
    void addFunctionMemberNode(const string& functonName,FunctionNode* functionNode){
        functionMemberNode[functonName] = functionNode;
        child.push_back(functionNode);
    }

    void setEntryNode(EntryNode* entryNode){
        this->entryNode = entryNode;
    }
    EntryNode* getEntryNode(){
        return this->entryNode;
    }
    bool check(){
        bool flag = true;
        if (getTypeInfo() == nullptr){
            printf("错误：没有类型（%s）的信息\n",typeName.data());
            flag = false;
        }
        else{
            //symbolTable.setCurrentClassScope(typeName);
            setClassScope(getTypeInfo());
            for (auto& fun : functionMemberNode){
                fun.second->setClassScope(getClassScope());
                if (fun.second->check() == false)
                    flag = false;
            }
            /*entryNode->setClassScope(getTypeInfo());
            if (entryNode->check() == false)
                flag = false;*/
        }
        return flag;
    }
    void toAsm(){
    }
    
};



struct ProcessStmtNode : public Node{
    ProcessStmtNode():Node(NodeKind::PROCESS_STATEMENT){}
    void toAsm(){
        for (Node* node : child){
            node->toAsm();
        }
    }
    virtual string getNodeKind(){
        return "程序语句(unknown)";
    }
};

struct ExpressionStmtNode : public ProcessStmtNode{
    ExpressionStmtNode(){}
    void toAsm(){
        usleep(100000);
        printf("正在编译表达式语句...\n");
        for (Node* node : child){
            node->toAsm();
            static_cast<ExpressionNode*>(node)->freeRegister();
            delete node;
        }
    }
    virtual string getNodeKind(){
        return "程序语句(表达式语句)";
    }
    bool check(){
        bool flag = true;
        for (Node* node : child){
            node->setClassScope(getClassScope());
            node->setFunctionScope(getFunctionScope());
            if (node->check() == false)
                flag = false;
        }
        
        return flag;
    }
};

/*
    if (a){
        a = 3;
    }

    cmp 寄存器 ,0
    je  L1;
    mov a = 3;
    JMP L2
L1:
L2:

    if (a)  a = 3;
    else    a = 2;

    cmp 寄存器，0
    je  L1
    mov a = 3
    jmp L2
L1:
    mov a = 2
L2;


    while(a)
        a = 3;

while_id_start:
    cmp 寄存器，0
    je  while_id_end;
    mov a = 3;
    jmp while_id_start
while_id_end:
*/

struct IfStmtNode : public ProcessStmtNode{
    ExpressionNode* exp;
    ProcessStmtNode* ifBody;
    ProcessStmtNode* elseBody;
    // 条件表达式 if_body else_body  elsebody可能为空
    IfStmtNode(ExpressionNode* exp,ProcessStmtNode* ifBody,ProcessStmtNode* elseBody){
        setConditionalExpression(exp);
        setIfBody(ifBody);
        setElseBody(elseBody);
        
        child.push_back(exp);
        child.push_back(ifBody);
        child.push_back(elseBody);
    }
    void setConditionalExpression(ExpressionNode* exp){
        this->exp = exp;
    }
    void setIfBody(ProcessStmtNode* ifBody){
        this->ifBody = ifBody;
    }
    void setElseBody(ProcessStmtNode* elseBody){
        this->elseBody = elseBody;
    }
    virtual string getNodeKind(){
        return "程序语句(if-else语句)";
    }
    bool check(){
        bool flag = true;

        exp->setClassScope(getClassScope());
        exp->setFunctionScope(getFunctionScope());
        if (exp->check() == false)
            flag = false;
        
        ifBody->setClassScope(getClassScope());
        ifBody->setFunctionScope(getFunctionScope());
        if (ifBody->check() == false)
            flag = false;
        
        if (elseBody != nullptr){
            elseBody->setClassScope(getClassScope());
            elseBody->setFunctionScope(getFunctionScope());
            if (elseBody->check() == false)
                flag = false;
        }

        return flag;
    }

    void toAsm(){
        /*    cmp 寄存器，0
    je  L1
    mov a = 3
    jmp L2
L1:
    mov a = 2
L2;*/
        usleep(100000);
        printf("正在编译if-else语句...\n");
        string label_1 = ASM::getRandomLabel();
        string label_2;

        if (elseBody != nullptr)
            label_2 = ASM::getRandomLabel();
        usleep(100000);
        printf("正在编译if-condition...\n");
        exp->toAsm();

        Register* reg = exp->getRegister();
        ASM::cmp(*reg,0);
        ASM::je(*reg,label_1);
        reg->freeRegister();
        usleep(100000);
        printf("正在编译if-body...\n");
        ifBody->toAsm();
        if (elseBody != nullptr)
        {
            label_2 = ASM::getRandomLabel();
            ASM::jmp(label_2);
        }

        ASM::setLabel(label_1);

        if (elseBody != nullptr){
            usleep(100000);
            printf("正在编译else-body...\n");
            elseBody->toAsm();
            ASM::setLabel(label_2);
        }

    }
};


struct WhileStmtNode : public ProcessStmtNode{
    static vector<string> whileEndLabels;
    static vector<string> whileStartLabels;
    ExpressionNode* exp;
    ProcessStmtNode* whileBody;
    string label_1,label_2;

    WhileStmtNode(ExpressionNode* exp,ProcessStmtNode* whileBody){
        setConditionalExpression(exp);
        setWhileBody(whileBody);

        child.push_back(exp);
        child.push_back(whileBody);
    }
    void setConditionalExpression(ExpressionNode* exp){
        this->exp = exp;
    }
    void setWhileBody(ProcessStmtNode* whileBody){
        this->whileBody = whileBody;
    }
    virtual string getNodeKind(){
        return "程序语句(while语句)";
    }
    void toAsm(){
        /*
while_id_start:
    cmp 寄存器，0
    je  while_id_end;
    mov a = 3;
    jmp while_id_start
while_id_end:*/
        usleep(100000);
        printf("正在编译while语句...\n");
        ASM::setLabel(label_1);

        usleep(100000);
        printf("正在编译while-condition...\n");
        exp->toAsm();
        exp->allocateRegister();
        Register* reg = exp->getRegister();
        
        ASM::cmp(*reg,0);
        ASM::je(*reg,label_2);
        exp->freeRegister();

        usleep(100000);
        printf("正在编译while-body...\n");
        whileBody->toAsm();
        ASM::jmp(label_1);
        ASM::setLabel(label_2);
    }

    bool check(){
        bool flag = true;

        label_1 = ASM::getRandomLabel();
        label_2 = ASM::getRandomLabel();
        whileStartLabels.push_back(label_1);
        whileEndLabels.push_back(label_2);

        exp->setClassScope(getClassScope());
        exp->setFunctionScope(getFunctionScope());
        if (exp->check() == false)
            flag = false;

        whileBody->setClassScope(getClassScope());
        whileBody->setFunctionScope(getFunctionScope());
        if (whileBody->check() == false)
            flag = false;

        whileStartLabels.pop_back();
        whileEndLabels.pop_back();
        return flag;
    }
};
inline vector<string> WhileStmtNode::whileEndLabels;
inline vector<string> WhileStmtNode::whileStartLabels;

struct ContinueStmtNode : public ProcessStmtNode{
    string whileStartLabel;
    ContinueStmtNode(){}
    virtual string getNodeKind(){
        return "程序语句(continue语句)";
    }
    bool check(){
        if (WhileStmtNode::whileEndLabels.empty() == true){
            printf("错误：continue语句只能在循环体中使用\n");
            return false;
        }
        whileStartLabel = WhileStmtNode::whileStartLabels.back();
        return true;
    }

    void toAsm(){
        usleep(100000);
        printf("正在翻译continue语句...\n");
        ASM::jmp(whileStartLabel);
    }
};
struct BreakStmtNode : public ProcessStmtNode{
    string whileEndLabel;
    BreakStmtNode(){}
    virtual string getNodeKind(){
        return "程序语句(break语句)";
    }
    bool check(){
        if (WhileStmtNode::whileEndLabels.empty() == true){
            printf("错误：break语句只能在循环体中使用\n");
            return false;
        }
        whileEndLabel = WhileStmtNode::whileEndLabels.back();
        return true;
    }

    void toAsm(){
        usleep(100000);
        printf("正在翻译break语句...\n");
        ASM::jmp(whileEndLabel);
    }
};

struct ReturnStmtNode : public ProcessStmtNode{
    ExpressionNode* exp;
    ReturnStmtNode(ExpressionNode* exp):exp(exp){}
    virtual string getNodeKind(){
        return "程序语句(return语句)";
    }
    bool check(){
        exp->setClassScope(getClassScope());
        exp->setFunctionScope(getFunctionScope());
        if (exp->check() == false)
            return false;

        if (exp->getResultTypeInfo()->typeKind == TypeKind::CLASS_TYPE && getFunctionScope()->returnType->typeKind != TypeKind::CLASS_TYPE){
            printf("错误：实际的返回值类型与函数声明的返回值类型不符\n");
            return false;
        }
        else if (exp->getResultTypeInfo()->typeKind != TypeKind::CLASS_TYPE && getFunctionScope()->returnType->typeKind == TypeKind::CLASS_TYPE){
            printf("错误：实际的返回值类型与函数声明的返回值类型不符\n");
            return false;
        }
        else if (exp->getResultTypeInfo()->typeKind == TypeKind::CLASS_TYPE && getFunctionScope()->returnType->typeKind == TypeKind::CLASS_TYPE){
            if (exp->getResultTypeInfo()->typeName != getFunctionScope()->returnType->typeName){
                printf("错误：实际的返回值类型与函数声明的返回值类型不符\n");
                return false;
            }
        }

        return true;
    }


    
    void toAsm(){
        usleep(100000);
        printf("正在翻译return语句...\n");
        VariableNode* ret = new VariableNode(getFunctionScope()->returnType,VariableKind::RETURN_TEMP);
        ret->setClassScope(getClassScope());
        ret->setFunctionScope(getFunctionScope());

        ExpressionNode* assign = new BinaryOperatorNode(ret,exp,OP::EQUAL);
        assign->setClassScope(getClassScope());
        assign->setFunctionScope(getFunctionScope());

        assign->toAsm();

        ASM::function_return();

        ret->freeRegister();
        exp->freeRegister();
        assign->freeRegister();
    }
};

struct PrintfStmtNode : public FunctionCallNode{
    StringNode* stringNode;
    PrintfStmtNode(StringNode* stringNode,vector<ExpressionNode*> parameters):FunctionCallNode("printf",parameters),stringNode(stringNode){
        child.push_back(stringNode);
        for (auto& param : parameters)
            child.push_back(param);
    }
    bool check(){
        this->setResultTypeInfo(symbolTable.getTypeInfo("int32"));
        
        bool flag = true;

        if (stringNode->check() == false)
            flag = false;

        for (auto& param : parameters){
            param->setClassScope(getClassScope());
            param->setFunctionScope(getFunctionScope());
            if (param->check() == false)
                flag = false;
        }
        return flag;
    }

    void setResultTypeInfo(TypeInfo* resultTypeInfo){
        this->resultTypeInfo = resultTypeInfo;
    }
    virtual string getNodeKind(){
        return "程序语句(printf语句)";
    }
    TypeInfo* getResultTypeInfo(){
        return this->resultTypeInfo;
    }
    
    void toAsm(){
        usleep(100000);
        printf("正在编译printf语句...\n");

        stringNode->toAsm();
        stringNode->freeRegister();
        string str = "printf";
        int size = 4;
        ASM::sub_esp(getResultTypeInfo()->size);        // 返回值临时空间
        for (auto& param : parameters){

            if (param->location == Location::CONSTANT)
                ASM::push_constant(param->getValue().front());
            else{
                param->toAsm();
                param->allocateRegister();
                //ASM::push_register(*(param->getRegister()));
                ASM::push(param->getValue(),*(param->getRegister()),param->getResultTypeInfo(),param->location);
                //param->freeRegister();
            }
            if (param->location == Location::RETURN)
                static_cast<FunctionCallNode*>(param)->freeReturnMemory = false;

            param->freeRegister();
            size = (size + param->getResultTypeInfo()->size + STACK_BYTES_ALIGNMENT - 1)/STACK_BYTES_ALIGNMENT*STACK_BYTES_ALIGNMENT;
        }
        ASM::push(stringNode->getValue().front());
        ASM::callFunction("",str);
        ASM::add_esp(size);     // 调用者清栈

        
        //ASM::add_esp(functionInfo->local_variable_block_size);
    }
};

/*
struct FunctionCallQueue{
    static set<FunctionNode*> flags;
    static vector<FunctionNode*> q;
    static void enQueue(const string& typeName,const string& functionName);
    static void toAsm();
};
*/

inline map<string,TypeNode*> typeNodeTable;

inline set<FunctionNode*> FunctionCallQueue::flags;
inline vector<FunctionNode*> FunctionCallQueue::q;

inline void FunctionCallQueue::enQueue(const string& typeName,const string& functionName){
    TypeNode* typeNode = typeNodeTable[typeName];
    FunctionNode* functionNode = typeNode->functionMemberNode[functionName];
    if (flags.count(functionNode) == 0){
        flags.insert(functionNode);
        q.push_back(typeNode->functionMemberNode[functionName]);
    }
}
inline void FunctionCallQueue::toAsm(){
    static int ind = 0;
    int size = q.size();

    while (ind < size)
    {
        q[ind]->toAsm();
        ind++;
    }
    
    if (size < q.size()){
        toAsm();
    }
}


inline vector<Node*> root;
#endif